package com.roin.learn.freemarker.freemarker;

import com.roin.learn.freemarker.dao.SysConfigMapper;
import com.roin.learn.freemarker.entity.SysConfig;
import com.roin.learn.freemarker.entity.SysConfigExample;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义系统参数值输出指令（标签）
 * 这个自字义指令（标签）只是通过code参数来输出指定的系统值，*在实际应用中，系统参数值更多的是写在数据库表中，
 * 在系统启动时把它们存入缓存（Ecahe,Redis等）
 * 例子：输出项目根路径<@sys code="basePath"/>
 */
@Component(value = "com.roin.learn.freemarker.freemarker.SystemValueDirective")
public class SystemValueDirective implements TemplateDirectiveModel {

    @Autowired
    SysConfigMapper sysConfigMapper;

    static Map<String, String> sysConfig;
    static final String PARAM_CODE = "code";
    static final String BASE_PATH = "basePath";

    public void execute(Environment environment, Map map, TemplateModel[] templateModels, TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
        //获取参数名为code的参数值，而且是必须提供的
        Object code = map.get(PARAM_CODE);
        if (code == null)
            throw new RuntimeException(" Parameters 'code' must be provided !");
        //如果sysConfig为空，说明第一次使用，要初始化系统配置值
        if (sysConfig == null) {
            sysConfig = new LinkedHashMap<String, String>();
            List<SysConfig> list = sysConfigMapper.selectByExample(new SysConfigExample());
            for (SysConfig sc : list) {
                sysConfig.put(sc.getSysCode(), sc.getSysVal());
            }
            ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            HttpServletRequest request = attr.getRequest();
            sysConfig.put(BASE_PATH, request.getContextPath());
        }
        //输出到页面
        Writer writer = environment.getOut();
        writer.write(sysConfig.get(code.toString()));
        //当标签内部不为空，即这样使用标签<@sys code='xxx'>123</@sys>，templateDirectiveBody值就不会为空，这时templateDirectiveBody.render(writer)
        //就是把标签内部的内容输出，内部可以嵌套其他标签
        if (templateDirectiveBody != null) {
            templateDirectiveBody.render(writer);
        }
    }
}
